/*
 * Middleware
 * Copyright (C) 2010/11
 * Riccardo Pulvirenti, Giuseppe Ravidà, Andrea Tino
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANDABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses
 */

/*!
 * File: core.hpp
 */

#ifndef _CORE_HPP_
#define _CORE_HPP_

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <boost/thread/mutex.hpp>

#include "core_exception.hpp"
#include "worker_descriptor.hpp"
#include "common_types.hpp"

//-----------------------------------------------------------------------------
// Constants
namespace middleware {
/*!
 * Default configuration file name.
 */
const std::string kConfigFileName = "core.config";
/*!
 * Default separator.
 */
const std::string kConfigFileDelimiter = ":";
/*!
 * Not found element.
 */
const std::string kParameterNotFound = "";
}
//-----------------------------------------------------------------------------
// Configuration parameters
namespace middleware {
/*!
 * Output etiquette.
 */
const std::string kCOREEtq = "CORE:      ";
/*!
 * Type for configuration parameters and values.
 */
typedef const std::string ConfigParam;
typedef const std::string ConfigValue;
/*!
 * Configuration parameters.
 */
ConfigParam kCPAddrBindIp = "CONFIG_ADDRME_IP";
ConfigParam kCPAddrManBindPort = "CONFIG_ADDRME_MAN_PORT";
ConfigParam kCPAddrDiscBindPort = "CONFIG_ADDRME_DISC_PORT";
ConfigParam kCPAddrUIBindPort = "CONFIG_ADDRME_UI_PORT";

ConfigParam kCPOtherPeersNum = "CONFIG_OTHERPEERS_NUM";
ConfigParam kCPAddrPeerXIpPre = "CONFIG_ADDRPEER_";
ConfigParam kCPAddrPeerXIpPost = "_IP";
ConfigParam kCPAddrPeerXTaskDescsPortPre = "CONFIG_ADDRPEER_";
ConfigParam kCPAddrPeerXTaskDescsPortPost = "_TASKS_PORT";
ConfigParam kCPAddrPeerXWorkerDescsPortPre = "CONFIG_ADDRPEER_";
ConfigParam kCPAddrPeerXWorkerDescsPortPost = "_WRKRS_PORT";
ConfigParam kCPAddrPeerXDataPortPre = "CONFIG_ADDRPEER_";
ConfigParam kCPAddrPeerXDataPortPost = "_DATA_PORT";

ConfigParam kCPWorkerCapabP = "CONFIG_WORKERCAPAB_P";
ConfigParam kCPWorkerCapabC = "CONFIG_WORKERCAPAB_C";
ConfigParam kCPWorkerCapabB = "CONFIG_WORKERCAPAB_B";
ConfigParam kCPWorkerCapabZ = "CONFIG_WORKERCAPAB_Z";
ConfigParam kCPWorkerCapabD = "CONFIG_WORKERCAPAB_D";
ConfigParam kCPWorkerCapabM = "CONFIG_WORKERCAPAB_M";
}
//-----------------------------------------------------------------------------
// Class definitions
namespace middleware {
/*!
 * Defines core for every machine (peer).
 */
class CORE {
public:
	/*!
	 * Constructor. Initalizes file name to default. Log files are set to
	 * random.
	 */
	CORE();
	/*!
	 * Constructor. Initalizes file name to parameter value.
	 */
	explicit CORE(const std::string& filename, const std::string& log_postfix);
	/*!
	 * Destructor.
	 */
	~CORE();
	/*!
	 * Executes, as single process, core.
	 */
	void exec();
	/*!
	 * Provides access to configuration file searching for param and returning
	 * its value. If no param is found, a null string is returned. The function
	 * looks for the first occurrence then exits.
	 */
	std::string operator[](const std::string& param_name) throw(CoreException);
private:
	/*!
	 * Initialization sequence.
	 */
	void bonjour() throw(CoreException);
	/*!
	 * Opens configuration file.
	 */
	void Open(std::ifstream& config_file) throw(CoreException);
	/*!
	 * Closes the file
	 */
	void Close(std::ifstream& config_file);
	/*!
	 * Configuration file name. Path will be local.
	 */
	std::string _config_filename;
	/*!
	 * Logers postfix.
	 */
	std::string _logger_postfix;
	/*!
	 * Maintains the set of worker descriptors used by worker and discovery
	 * to send status and find best worker.
	 */
	PeersSet _peers_worker_descriptors;
	/*!
	 * Mutex for vector of worker descriptor.
	 */
	boost::mutex _peers_worker_descriptors_mutex;
}; /* CORE */
} /* middleware */

#endif
